<!--
 * @Descripttion: 分析管理-分析任务管理
 * @version: V1.0.0.1
 * @Author: zhaozhenzhuo
 * @Date: 2025-10-22 10:43:57
 * @LastEditors: zhaozhenzhuo
 * @LastEditTime: 2025-10-22 10:43:57
-->
<template>
	<div class="analysis-task-manage-page">
		<div class="manage-layout search-wrapper">
			<div class="title-wrapper">
				<span class="title">分析任务筛选</span>
			</div>
			<div class="content-wrapper justify-between">
				<div class="filter-item-wrapper">
					<div class="filter-item">
						<span class="item-label">学期</span>
						<el-select
							v-model="queryObj.termCode"
							placeholder="请选择学期"
							filterable
							@change="onSearchHandle"
						>
							<el-option
								v-for="item in termList"
								:key="item.code"
								:label="item.name"
								:value="item.code"
							>
							</el-option>
						</el-select>
					</div>
					<div class="filter-item">
						<span class="item-label">学院</span>
						<el-select
							v-model="queryObj.academyCode"
							placeholder="请选择学院"
							clearable
							filterable
							@change="onSearchHandle"
						>
							<el-option
								v-for="item in academyList"
								:key="item.code"
								:label="item.name"
								:value="item.code"
							></el-option>
						</el-select>
					</div>
					<div class="filter-item">
						<span class="item-label">授课地点</span>
						<CascaderSelect
							:position-default-option="positionDefaultOption"
							cascader-placeholder="请选择授课地点"
							@cascaderSelectData="cascaderSelectDataHandle"
						/>
					</div>
					<div class="filter-item">
						<span class="item-label">AI分析状态</span>
						<el-select
							v-model="queryObj.aiLessonTaskStatus"
							placeholder="请选择AI分析状态"
							clearable
							@change="onSearchHandle"
						>
							<el-option
								v-for="item in aiStatusList"
								:key="item.code"
								:label="item.name"
								:value="item.code"
							></el-option>
						</el-select>
					</div>
					<div class="filter-item">
						<span class="item-label">授课时间</span>
						<el-date-picker
							v-model="queryObj.timeRange"
							type="daterange"
							range-separator="至"
							start-placeholder="开始日期"
							end-placeholder="结束日期"
							value-format="YYYY-MM-DD HH:mm:ss"
							:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]"
							@change="onSearchHandle"
						>
						</el-date-picker>
					</div>
					<div class="filter-item">
						<el-input
							v-model="queryObj.searchValue"
							class="item-input margin-right"
							placeholder="课程名/课程号或老师名/工号"
							@change="onSearchHandle"
						>
						</el-input>
						<div class="search-btn" @click="onSearchHandle">筛选</div>
					</div>
				</div>
				<div class="btns-wrapper static">
					<label>自动分析:</label>
					<el-radio-group v-model="isAutoAI" @change="setAIASConfig">
						<el-radio :value="1">开</el-radio>
						<el-radio :value="0">关</el-radio>
					</el-radio-group>
					<span class="config-text" @click="showConfigDialog">自动分析配置</span>
					<div class="btn-item" @click="onBatchDeleteLessonReportHandle">批量删除</div>
				</div>
			</div>
		</div>

		<div class="manage-layout data-wrapper">
			<div class="title-wrapper">
				<span class="title">分析任务列表</span>
			</div>
			<!-- 表格 -->
			<div class="table-wrapper">
				<el-table
					:data="tableData"
					stripe
					fit
					class="self-stripe-table"
					height="100%"
					:header-cell-class-name="handleHeaderClass"
					@sort-change="handleTableSort"
					@selection-change="onSelectionChangeHandle"
				>
					<el-table-column
						type="selection"
						width="55"
						align="center"
						:selectable="
							(row: TableDataItem) => row.aiStatus === 3 || row.aiStatus === 4 || row.aiStatus === 5
						"
					>
					</el-table-column>
					<el-table-column label="序号" type="index" :index="indexMethod" align="center" width="80">
					</el-table-column>
					<el-table-column label="课程名称" min-width="10.5%" prop="name" show-overflow-tooltip>
					</el-table-column>
					<el-table-column label="课程号" min-width="7%" prop="subjectCode" show-overflow-tooltip>
					</el-table-column>
					<el-table-column label="开课学院" min-width="9%" prop="academyName" show-overflow-tooltip>
					</el-table-column>
					<el-table-column label="授课老师" min-width="8%" show-overflow-tooltip>
						<template #default="scope">
							{{ scope.row.teacherNames || '--' }}
						</template>
					</el-table-column>
					<el-table-column
						label="授课时间"
						align="center"
						min-width="13.5%"
						sortable="custom"
						:sort-orders="sortOrders"
						show-overflow-tooltip
					>
						<template #default="scope">
							<p v-if="scope.row.beginTime && scope.row.endTime" class="overflow">
								{{ formatTime(scope.row.beginTime, 'YYYY/MM/DD HH:mm') }} -
								{{ formatTime(scope.row.endTime, 'HH:mm') }}
							</p>
							<p v-else>--</p>
						</template>
					</el-table-column>
					<el-table-column label="授课地点" min-width="10%" prop="roomName" show-overflow-tooltip>
					</el-table-column>
					<el-table-column label="AI分析状态" min-width="9%" show-overflow-tooltip>
						<template #default="scope">
							<p :class="aiStatusMap[scope.row.aiStatus]?.color">
								{{ aiStatusMap[scope.row.aiStatus]?.label }}
							</p>
						</template>
					</el-table-column>
					<el-table-column
						label="最近分析时间"
						align="center"
						min-width="13%"
						show-overflow-tooltip
						sortable="custom"
						:sort-orders="sortOrders"
					>
						<template #default="scope">
							<p v-if="scope.row.lastAiTime" class="overflow">
								{{ formatTime(scope.row.lastAiTime, 'YYYY/MM/DD HH:mm') }}
							</p>
							<p v-else>--</p>
						</template>
					</el-table-column>
					<el-table-column label="操作" align="center" min-width="33%">
						<template #default="scope">
							<el-button type="text" @click="getPlyerList(scope.row)">点播</el-button>
							<el-button
								type="text"
								:disabled="
									scope.row.aiStatus === 1 || scope.row.aiStatus === 2 || scope.row.aiStatus === 6
								"
								@click="openAILessonTask(scope.row)"
								>AI分析</el-button
							>
							<el-button
								type="text"
								:disabled="
									scope.row.aiStatus === -1 ||
									scope.row.aiStatus === 0 ||
									scope.row.aiStatus === 1 ||
									scope.row.aiStatus === 6
								"
								@click="getAILessonTaskProgress(scope.row, true)"
								>查看分析过程</el-button
							>
							<!-- AI分析总状态 0:未开始 11:排队中 1:进行中 2:已结束 3:已结束，有异常 -->
							<el-button
								type="text"
								:disabled="scope.row.aiStatus !== 3"
								:title="scope.row.aiStatus !== 3 ? '当前课堂未生成报告' : ''"
								@click="onViewAnalysisResultHandle(scope.row.lessonCode)"
								>查看分析结果</el-button
							>
							<el-button
								type="text"
								:disabled="
									scope.row.aiStatus !== 3 && scope.row.aiStatus !== 4 && scope.row.aiStatus !== 5
								"
								:title="
									scope.row.aiStatus !== 3 && scope.row.aiStatus !== 4 && scope.row.aiStatus !== 5
										? '只能删除已分析结束的课堂报告'
										: ''
								"
								@click="onDeleteLessonReportHandle(scope.row)"
								>删除报告</el-button
							>
						</template>
					</el-table-column>
				</el-table>
			</div>
		</div>
		<!-- 分页 -->
		<div v-if="pagination.totalPages > 1" class="pagination-wrapper">
			<el-pagination
				:current-page="pagination.currentPage"
				:total="pagination.totalCount"
				:page-size="pagination.numPerPage"
				background
				:hide-on-single-page="true"
				@current-change="onCurrentChangeHandle"
			/>
		</div>

		<!-- 自动分析配置 -->
		<el-dialog
			v-model="configVisible"
			title="自动分析配置 (说明:此处选中教室的课程将在自动分析打开时，系统自动开启AI分析)"
			class="self-dialog"
			align-center
			:close-on-click-modal="false"
		>
			<div class="config-dialog-wrap">
				<div v-for="item in roomList" :key="item.code" class="build-list-wrap">
					<!-- 楼层名字 -->
					<div class="floor-name">{{ item.name }}</div>
					<div v-for="(item2, index) in item.floorList" :key="index" class="floor-item">
						<div class="floor-text">
							{{ String(item2.buildingFloorNo).replace('-', 'B') }}层 ({{
								item2.roomList?.length
							}}间)
						</div>
						<div class="room-list-wrap">
							<div
								v-for="roomItem in item2.roomList"
								:key="roomItem.id"
								class="room-item"
								:class="{ 'room-item-active': roomItem.select }"
								:title="roomItem.name"
								@click="selectItem(roomItem)"
							>
								{{ roomItem.name }}
							</div>
						</div>
					</div>
				</div>
			</div>
			<template #footer>
				<div class="dialog-footer">
					<el-button @click="configVisible = false">取 消</el-button>
					<el-button type="primary" @click="handleOK">确 定</el-button>
				</div>
			</template>
		</el-dialog>

		<!-- 任务进度详情弹框 -->
		<el-dialog
			v-if="taskProgressDialog.visible"
			width="80%"
			v-model="taskProgressDialog.visible"
			:title="taskProgressDialog.title"
			class="self-dialog progress-dialog"
			align-center
			:close-on-click-modal="false"
			@opened="setTaskLineLength"
			@close="taskProgressDialogCloseHandle"
		>
			<div class="progress-dialog-wrap">
				<el-table :data="taskProgressDetail" fit class="self-stripe-table no-background">
					<el-table-column label="分析任务" min-width="20%">
						<template #default="scope">
							<span
								:class="{
									'task-circle': aiTaskOrder.includes(scope.row.name),
									'subtask-circle': !aiTaskOrder.includes(scope.row.name),
									'circle-flag': true
								}"
								><span
									:class="{
										'vertical-line': scope.$index === 0
									}"
								></span
							></span>
							<span :class="{ 'has-font-size': aiTaskOrder.includes(scope.row.name) }">{{
								aiTaskMap[scope.row.name]
							}}</span>
						</template></el-table-column
					>
					<el-table-column label="状态" min-width="8%">
						<template #default="scope">
							<span :class="aiStatusMap[scope.row.status]?.color">{{
								aiStatusMap[scope.row.status]?.label || '--'
							}}</span>
						</template>
					</el-table-column>
					<el-table-column label="分析服务名称" min-width="13%">
						<template #default="scope">
							<span v-if="scope.row.serverName" class="center">{{ scope.row.serverName }}</span>
							<span v-else class="center">--</span>
						</template>
					</el-table-column>
					<el-table-column label="任务开始时间" align="center" min-width="13%">
						<template #default="scope">
							<span v-if="scope.row.bgTime" class="center"
								>{{ formatTime(scope.row.bgTime, 'YYYY/MM/DD HH:mm') }}
							</span>
							<span v-else class="center">--</span>
						</template>
					</el-table-column>
					<el-table-column label="任务结束时间" align="center" min-width="13%">
						<template #default="scope">
							<span v-if="scope.row.edTime" class="center"
								>{{ formatTime(scope.row.edTime, 'YYYY/MM/DD HH:mm') }}
							</span>
							<span v-else class="center">--</span>
						</template>
					</el-table-column>
					<el-table-column label="耗时" min-width="12%">
						<template #default="scope">
							<span v-if="scope.row.bgTime && scope.row.edTime"
								>{{ formatDuration(scope.row.bgTime, scope.row.edTime) }}
							</span>
							<span v-else-if="scope.row.bgTime && !scope.row.edTime">{{
								formatDuration(scope.row.bgTime, new Date().getTime())
							}}</span>
							<span v-else>--</span>
						</template>
					</el-table-column>
					<el-table-column label="异常预警信息" min-width="13%">
						<template #default="scope">
							<span v-if="scope.row.msg" class="txt-danger">{{ scope.row.msg }}</span>
							<span v-else class="txt-secondary">暂无</span>
						</template>
					</el-table-column>
					<el-table-column label="操作" align="center" min-width="8%">
						<template #default="scope">
							<span
								v-if="
									scope.row.isRefresh &&
									(scope.row.status === 3 || scope.row.status === 4 || scope.row.status === 5)
								"
								class="refresh"
								@click="onRefreshHandle(scope.row)"
								>重新分析</span
							>
							<span v-else>--</span>
						</template>
					</el-table-column>
				</el-table>
			</div>
		</el-dialog>

		<!-- 点播弹框 -->
		<el-dialog
			class="self-dialog video-play-dialog"
			v-model="playDialogVisible"
			:title="`点播录像资源${curPlayerLesson?.name ? `（${curPlayerLesson.name}）` : ''}`"
			align-center
			:close-on-click-modal="false"
			destroy-on-close
		>
			<div class="video-play-content">
				<!-- 播放器 -->
				<div class="player-wrap">
					<VideoPlayer :videojs-data="videojsData" :is-covered="isCovered" :is-delete="isDelete" />
				</div>
				<!-- 录像片段列表 -->
				<div class="fragment-box">
					<el-collapse v-model="activeFragmentKey">
						<el-collapse-item
							v-for="item in fragmentList"
							:key="item.id"
							:title="item.device?.name || '--'"
							:name="item.id"
						>
							<div>
								<ul class="fragment-wrap">
									<li
										v-for="file in item.files"
										:key="file.id"
										class="fragment"
										:class="{ active: videojsData?.videoId === file.id }"
									>
										<span class="file-name" @click="changePlayFragment(file, item.status)">
											{{ fitlerFileName(file.filename) }}
										</span>
										<span class="copy-btn" @click="copyUrl(file.url, item)">复制链接</span>
										<span class="download-btn" @click="downloadFragment(file, item)">下载</span>
									</li>
								</ul>
							</div>
						</el-collapse-item>
					</el-collapse>
				</div>
			</div>
		</el-dialog>
	</div>
</template>

<script setup lang="ts">
import { v4 as uuidv4 } from 'uuid';
import { onMounted, ref, reactive, onUnmounted, nextTick, getCurrentInstance } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useRouter } from 'vue-router';
import CascaderSelect from '@/components/common/CascaderSelect.vue';
import VideoPlayer from '@/components/player/VideoPlayer.vue';
import { formatTime, formatDuration } from '@/assets/js/utils';
import type {
	QueryObj,
	Term,
	CurTerm,
	Academy,
	Location,
	RoomListItem,
	FloorItem,
	RoomItem,
	TableDataItem,
	TaskProgressKeyType,
	TaskProgressItemType,
	TaskProgressDetailItem,
	FragmentItem,
	VideoDataType,
	FileType,
	CustomTableColumn
} from './AnalysisTaskManage.types';
import {
	getErrorMessage,
	getTermListAPI,
	getTerm4DayAPI,
	getOrganizationListAPI,
	getAIASConfigAPI,
	setAIASConfigAPI,
	getCheckRoomListAPI,
	getAiAutomaticAnalysisAPI,
	batchAddAiAutomaticAnalysisAPI,
	getLessonPageForManageAPI,
	delLessonReportAPI,
	openAILessonTaskAPI,
	getAILessonTaskProgressAPI,
	getResourceByLessonCodeAPI
} from '@/api/index';
import type { BaseListItemType, PaginationType } from '@/api/index';

// 在 setup 顶层获取实例
const instance = getCurrentInstance();
const router = useRouter();

onMounted(() => {
	// 初始化
	init();
});

onUnmounted(() => {
	if (timer.value) {
		clearTimeout(timer.value);
	}
	if (subtimer.value) {
		clearTimeout(subtimer.value);
	}
	window.removeEventListener('resize', resizeEvent);
});

/* ------过滤条件相关------ */
// 过滤条件
const queryObj = ref<QueryObj>({
	termCode: '',
	academyCode: '',
	searchValue: '',
	aiLessonTaskStatus: '',
	campusCode: '',
	buildingCode: '',
	roomCode: '',
	timeRange: []
});

// 学期列表
const termList = ref<Term[]>([]);
// 获取学期列表
const getTermList = async () => {
	try {
		const data = await getTermListAPI();
		termList.value = data.list;
	} catch (err) {
		console.error(getErrorMessage(err));
	}
};
// 获取当前学期
const curTerm = ref<CurTerm | null>(null);
const getCurTerm = async () => {
	try {
		const data = await getTerm4DayAPI(null);
		curTerm.value = data;
		queryObj.value.termCode = data?.code || '';
	} catch (err) {
		console.error(getErrorMessage(err));
	}
};

// 学院列表
const academyList = ref<Academy[]>([]);
// 获取学院列表
const getAcademyList = async () => {
	try {
		const data = await getOrganizationListAPI({ type: 'Academy', academyType: 1 });
		academyList.value = data.list;
	} catch (err) {
		console.error(getErrorMessage(err));
	}
};

/* ------授课地点相关------ */
// 授课地点级联选择初始值
const positionDefaultOption = ref<string[]>([]);
// 教室位置筛选 value 校区、教学楼、教室组成的数组
const cascaderSelectDataHandle = (obj: Location) => {
	queryObj.value = { ...queryObj.value, ...obj };
	onSearchHandle();
};

/* ------AI分析状态相关------ */
// AI分析状态列表
const aiStatusList = ref<BaseListItemType[]>([
	{
		code: 0,
		name: '未分析'
	},
	{
		code: 1,
		name: '分析排队中'
	},
	{
		code: 2,
		name: '分析中'
	},
	{
		code: 3,
		name: '分析完成'
	},
	{
		code: 4,
		name: '分析异常'
	}
]);
// 分析返回数据状态Map
const aiStatusMap = ref<{ [key: number]: { label: string; color: string } }>({
	'-1': { label: '未分析', color: 'txt-secondary' },
	'0': { label: '未分析', color: 'txt-secondary' },
	'1': { label: '分析排队中', color: 'txt-warning' },
	'2': { label: '分析中...', color: 'txt-brand' },
	'3': { label: '分析完成', color: 'txt-regular' },
	'4': { label: '分析异常', color: 'txt-danger' },
	'5': { label: '分析异常', color: 'txt-danger' },
	'6': { label: '分析排队中', color: 'txt-warning' }
});

/* ------自动分析相关------ */
// 是否开启自动分析
const isAutoAI = ref<number>(0);
// 获取aice配置信息
const getAIASConfig = async () => {
	try {
		const data = await getAIASConfigAPI();
		if (!data) {
			// 兼容异常
			isAutoAI.value = 0;
		} else {
			isAutoAI.value = data.isAutoAI;
		}
	} catch (err) {
		isAutoAI.value = 0;
		console.error(getErrorMessage(err));
	}
};
// 设置是否自动分析
const setAIASConfig = () => {
	ElMessageBox.confirm(
		isAutoAI.value ? '开启后，课程结束会自动开始分析。' : '是否关闭自动分析？',
		'提示',
		{
			confirmButtonText: '确定',
			cancelButtonText: '取消',
			type: 'warning'
		}
	)
		.then(async () => {
			try {
				await setAIASConfigAPI<void>({ isAutoAI: isAutoAI.value });
				ElMessage.success('设置成功！');
			} catch (err) {
				ElMessage.error(getErrorMessage(err));
			} finally {
				getAIASConfig();
			}
		})
		.catch(() => {
			isAutoAI.value = isAutoAI.value ? 0 : 1;
		});
};

/* ------自动分析配置相关------ */
// 自动分析配置弹窗是否显示
const configVisible = ref<boolean>(false);
const roomList = ref<RoomListItem[]>([]);
// 获取教室自动分析列表
const getAiAutomaticAnalysis = async () => {
	const params = {
		businessType: 1
	};
	let data: string[] | null = null;
	try {
		data = await getAiAutomaticAnalysisAPI(params);
	} catch (err) {
		console.error(getErrorMessage(err));
	}
	return data;
};
// 获取教室列表
const getCheckRoomList = async () => {
	const params = {
		buildingCode: '',
		buildingFloorNo: '',
		type: null,
		name: '',
		roomTypeId: ''
	};

	try {
		const data = await getCheckRoomListAPI(params);
		const businessCodeList = await getAiAutomaticAnalysis();

		roomList.value = data.map((floorItem) => {
			const sortedData = floorItem.roomList.sort((a, b) => a.buildingFloorNo - b.buildingFloorNo);

			const result: FloorItem[] = [];
			sortedData.forEach((item) => {
				const _item: RoomItem = JSON.parse(JSON.stringify(item));
				if (businessCodeList && businessCodeList.includes(_item.code)) {
					_item.select = true;
				} else {
					_item.select = false;
				}

				const existing = result.find((r) => r.buildingFloorNo === _item.buildingFloorNo);
				if (!existing) {
					result.push({ buildingFloorNo: _item.buildingFloorNo, roomList: [_item] });
				} else {
					existing.roomList.push(_item);
				}
			});

			return {
				...floorItem,
				floorList: result
			};
		});
	} catch (err) {
		console.error(getErrorMessage(err));
	}
};
// 显示配置教室弹窗
const showConfigDialog = () => {
	configVisible.value = true;
	getCheckRoomList();
};

// 设置教室是否选中状态
const selectItem = (roomItem: RoomItem) => {
	roomItem.select = !roomItem.select;
};

// 确认提交
const handleOK = () => {
	const codeList: string[] = [];

	roomList.value.forEach((item) => {
		if (item.floorList) {
			item.floorList.forEach((item2) => {
				item2.roomList.forEach((item3) => {
					if (item3.select) {
						codeList.push(item3.code);
					}
				});
			});
		}
	});

	batchAddAiAutomaticAnalysis(codeList);
};

// 批量添加自动分析配置信息
const batchAddAiAutomaticAnalysis = async (codeList: string[]) => {
	const params = {
		businessType: 1,
		businessCodes: codeList
	};
	try {
		await batchAddAiAutomaticAnalysisAPI(params);
		ElMessage.success('添加成功！');
		configVisible.value = false;
	} catch (err) {
		ElMessage.error(getErrorMessage(err));
	}
};

// 分页信息
const pagination = reactive<PaginationType>({
	currentPage: 1,
	numPerPage: 20,
	totalCount: 0,
	totalPages: 0
});

// 过滤条件筛选回调
const onSearchHandle = () => {
	pagination.currentPage = 1;
	getLessonPageForManage();
};

// 当前页改变
const onCurrentChangeHandle = (page: number) => {
	pagination.currentPage = page;
	getLessonPageForManage();
};

/** 初始化 */
const init = async () => {
	getTermList();
	getAcademyList();
	getAIASConfig();
	await getCurTerm();

	// 返回时如果sessionStorage中有值，则赋初始值
	queryObj.value.termCode = curTerm.value?.code || '';
	getLessonPageForManage();
	window.addEventListener('resize', resizeEvent);
};

// 排序字段
const sortStr = ref<string>('beginTime:desc|lastAiTime:desc');
// 表格数据
const tableData = ref<TableDataItem[]>([]);
// 正在分析的课堂列表
const beingAILessons = ref<string[]>([]);
// 轮询查询课堂列表定时器
const timer = ref<ReturnType<typeof setTimeout> | null>(null);
// 获取课堂列表
const getLessonPageForManage = async () => {
	getLessonPageForManageAPI({
		termCode: queryObj.value.termCode,
		academyCode: queryObj.value.academyCode,
		searchValue: queryObj.value.searchValue,
		aiLessonTaskStatus:
			queryObj.value.aiLessonTaskStatus || queryObj.value.aiLessonTaskStatus === 0
				? queryObj.value.aiLessonTaskStatus === 4
					? [4, 5]
					: queryObj.value.aiLessonTaskStatus === 0
					? [-1, 0]
					: [queryObj.value.aiLessonTaskStatus as number]
				: null,
		campusCode: queryObj.value.campusCode,
		buildingCode: queryObj.value.buildingCode,
		roomCode: queryObj.value.roomCode,
		beginTime: queryObj.value.timeRange?.length
			? new Date(queryObj.value.timeRange[0]).getTime()
			: undefined,
		endTime: queryObj.value.timeRange?.length
			? new Date(queryObj.value.timeRange[1]).getTime()
			: undefined,
		pageNum: pagination.currentPage,
		pageSize: pagination.numPerPage,
		sort: sortStr.value
	})
		.then((data) => {
			tableData.value = data.list;
			pagination.currentPage = data.currentPage;
			pagination.numPerPage = data.numPerPage;
			pagination.totalCount = data.totalCount;
			pagination.totalPages = data.totalPages;
			// 筛选出正在分析中的课堂
			beingAILessons.value = data.list
				.filter((lesson) => lesson.aiStatus === 1 || lesson.aiStatus === 2 || lesson.aiStatus === 6)
				.map((lesson) => {
					return lesson.lessonCode;
				});
			// 存在正在分析的课堂，轮询分析总状态
			if (beingAILessons.value.length) {
				pollAIStatus();
			} else if (timer.value) {
				clearTimeout(timer.value);
			}
		})
		.catch((err) => {
			console.error(getErrorMessage(err));
		});
};

// 轮询分析总状态
const pollAIStatus = () => {
	if (timer.value) {
		clearTimeout(timer.value);
	}
	timer.value = setTimeout(() => {
		getLessonPageForManage();
	}, 1 * 60 * 1000);
};

// 序号
const indexMethod = (index: number) => {
	return (pagination.currentPage - 1) * pagination.numPerPage + index + 1;
};

/** 排序相关 */
// 是否是第一次渲染表格
const isFirst = ref<boolean>(true);
// 存储排序规则 orderColumn排序列表头label orderState排序列排序状态
const ordersList = ref<{ orderColumn: string; orderState: string }[]>([
	{ orderColumn: '授课时间', orderState: 'descending' },
	{ orderColumn: '最近分析时间', orderState: 'descending' }
]);
// 排序顺序
const sortOrders = ref<('descending' | 'ascending' | null)[]>(['descending', 'ascending', null]);
// 设置列的排序为我们自定义的排序
const handleHeaderClass = ({ column }: { column: CustomTableColumn }) => {
	// 面包屑返回时，将排序状态重新赋给表格数据
	if (isFirst.value) {
		const ceil = ordersList.value.find((item) => item.orderColumn === column.orderColumn);
		if (ceil) {
			column.multiOrder = ceil.orderState;
		} else {
			// 默认值为降序
			column.multiOrder = 'descending';
		}
		if (column.label === '操作') {
			isFirst.value = false;
		}
	}
	column.order = column.multiOrder; // descending
};
// 列表排序
const handleTableSort = ({ column, order }: { column: CustomTableColumn; order: string }) => {
	// 有些列不需要排序，提前返回
	if (column.sortable !== 'custom') {
		return;
	}

	column.multiOrder = order;
	// 页码数重置
	pagination.currentPage = 1;

	const result = ordersList.value.find((e) => e.orderColumn === column.label);
	if (result) {
		result.orderState = column.multiOrder;
	} else {
		ordersList.value.push({
			orderColumn: column.label,
			orderState: column.multiOrder
		});
	}

	handleOrderChange();
};
// 存储排序规则
const handleOrderChange = () => {
	// 处理传参
	const _beginTimeColumn = ordersList.value.find((e) => e.orderColumn === '授课时间');
	const _lastAiTimeColumn = ordersList.value.find((e) => e.orderColumn === '最近分析时间');

	let _beginTimeStr = '';
	let _lastAiTimeStr = '';

	if (_beginTimeColumn && _beginTimeColumn.orderState === 'ascending') {
		_beginTimeStr = 'beginTime:asc';
	} else if (_beginTimeColumn && _beginTimeColumn.orderState === 'descending') {
		_beginTimeStr = 'beginTime:desc';
	}
	if (_lastAiTimeColumn && _lastAiTimeColumn.orderState === 'ascending') {
		_lastAiTimeStr = 'lastAiTime:asc';
	} else if (_lastAiTimeColumn && _lastAiTimeColumn.orderState === 'descending') {
		_lastAiTimeStr = 'lastAiTime:desc';
	}
	sortStr.value = `${_beginTimeStr}${_beginTimeStr && _lastAiTimeStr ? '|' : ''}${_lastAiTimeStr}`;
	// 重新获取列表
	getLessonPageForManage();
};

/** 删除报告相关 */
// 当前选中的列表
const selectionList = ref<TableDataItem[]>([]);
// 选中项改变触发的事件
const onSelectionChangeHandle = (list: TableDataItem[]) => {
	selectionList.value = list;
};
// 删除课堂报告
const onDeleteLessonReportHandle = (row: TableDataItem) => {
	ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
		confirmButtonText: '确定',
		cancelButtonText: '取消',
		type: 'warning'
	}).then(async () => {
		try {
			await delLessonReportAPI({ lessonCodes: row.lessonCode });
			ElMessage.success('删除成功！');
			getLessonPageForManage();
		} catch (err) {
			ElMessage.error(getErrorMessage(err));
		}
	});
};
// 批量删除课堂报告
const onBatchDeleteLessonReportHandle = () => {
	if (!selectionList.value.length) {
		ElMessage.warning('最少选择一项');
		return;
	}
	ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
		confirmButtonText: '确定',
		cancelButtonText: '取消',
		type: 'warning'
	}).then(async () => {
		const lessonCodes = selectionList.value
			.filter((item) => item.lessonCode)
			.map((item) => item.lessonCode)
			.join(',');
		try {
			await delLessonReportAPI({ lessonCodes });
			ElMessage.success('删除成功！');
			getLessonPageForManage();
		} catch (err) {
			ElMessage.error(getErrorMessage(err));
		}
	});
};

// 查看分析结果
const onViewAnalysisResultHandle = (lessonCode: string) => {
	router.push({
		name: 'LessonAnalysisDetails',
		query: {
			lessonCode,
			from: 'taskManage'
		}
	});
};

/** 开启分析 */
// 开启AI分析任务
const openAILessonTask = (
	lesson: TableDataItem | null,
	type: string | undefined = undefined,
	llmNodeTypes: string[] = []
) => {
	let confirmInfo = '';
	if (type) {
		// 重新分析子任务
		confirmInfo = '是否重新分析该任务?';
	} else {
		// 分析整节课
		confirmInfo = '是否对此节课堂开启AI分析?';
	}

	ElMessageBox.confirm(`${confirmInfo}`, '提示', {
		confirmButtonText: '确定',
		cancelButtonText: '取消',
		type: 'warning'
	}).then(async () => {
		try {
			if (!type || type === 'resultProcess') {
				await openAILessonTaskAPI({ lessonCodeList: [lesson?.lessonCode || ''], type });
			} else {
				await openAILessonTaskAPI({
					lessonCodeList: [lesson?.lessonCode || ''],
					type,
					llmNodeTypes
				});
			}
		} catch (err) {
			console.error(getErrorMessage(err));
		}
		ElMessage.success('开启成功！');
		if (type) {
			getAILessonTaskProgress(curLesson.value);
		} else {
			// 页面先更改AI分析状态
			if (lesson) {
				lesson.aiStatus = 2;
			}
			// 清除当前轮询的定时器
			if (timer.value) {
				clearTimeout(timer.value);
			}
			// 5s后开始轮询
			timer.value = setTimeout(() => {
				getLessonPageForManage();
			}, 5 * 1000);
		}
	});
};

// 是否显示任务进度弹窗
const flag = ref<boolean>(false);
// 获取AI分析任务进度详情
const getAILessonTaskProgress = (curLesson: TableDataItem | null, flg = false) => {
	if (flg) {
		flag.value = false;
	}
	getAILessonTaskProgressFun(curLesson);
};

// 轮询AI分析任务进度详情
const subtimer = ref<ReturnType<typeof setTimeout> | null>(null);
const pollAILessonTaskProgress = () => {
	if (subtimer.value) {
		clearTimeout(subtimer.value);
	}
	subtimer.value = setTimeout(() => {
		getAILessonTaskProgressFun(curLesson.value);
	}, 10 * 1000);
};

// 任务进度详情弹框关闭时，销毁定时器
const taskProgressDialogCloseHandle = () => {
	if (subtimer.value) {
		clearTimeout(subtimer.value);
	}
};

// 查询AI分析任务进度详情
const curLesson = ref<TableDataItem | null>(null);
const taskProgressDialog = ref<{ title: string; visible: boolean }>({ title: '', visible: false });
// 分析流程名称Map
const aiTaskMap = ref<{ [key: string]: string }>({});
// 一级分析流程顺序
const aiTaskOrder = ref<TaskProgressKeyType[]>([]);
// AI分析任务进度详情数据
const taskProgressDetail = ref<TaskProgressDetailItem[]>([]);
const getAILessonTaskProgressFun = (lesson: TableDataItem | null) => {
	curLesson.value = lesson;
	taskProgressDialog.value.title = `分析详情（${lesson?.name}）`;
	getAILessonTaskProgressAPI({ lessonCode: lesson?.lessonCode || '' })
		.then((res) => {
			// 获取一级任务
			if (res && Object.keys(res).length) {
				const _firstLevel: { key: TaskProgressKeyType; order: number }[] = [];
				(Object.keys(res) as TaskProgressKeyType[]).forEach((key) => {
					const _item = res[key];
					if (key && _item && Number.isFinite(_item.order)) {
						_firstLevel.push({ key, order: _item.order });
					}
				});
				aiTaskOrder.value = _firstLevel.sort((a, b) => a.order - b.order).map((item) => item.key);
			}

			// 获取分析流程名称Map
			aiTaskMap.value = {};
			(Object.keys(res) as TaskProgressKeyType[]).forEach((key) => {
				const _item = res[key];
				if (key && _item && _item.name) {
					aiTaskMap.value[key] = _item.name;
				}
				if (_item && _item.taskList && _item.taskList.length) {
					_item.taskList.forEach((item) => {
						if (item.name && item.type) {
							aiTaskMap.value[item.type] = item.name;
						}
					});
				}
			});

			// 任务排序
			const data: { task: TaskProgressKeyType; value: TaskProgressItemType }[] = [];
			aiTaskOrder.value.forEach((task) => {
				data.push({ task, value: res[task] });
			});
			taskProgressDetail.value = [];
			data.forEach((task) => {
				taskProgressDetail.value.push({
					name: task.task,
					status: task.value.status,
					serverName: task.value.serverName,
					bgTime: task.value.bgTime,
					edTime: task.value.edTime,
					order: task.value.order || 0,
					msg: task.value.msg || '',
					level: 1,
					isRefresh:
						task.task === 'pptTask' ||
						task.task === 'llmTask' ||
						task.task === 'audioTask' ||
						task.task === 'behaviorRecognitionResp' ||
						task.task === 'resultProcess' // 是否可以重新分析
				});

				const _taskList = task.value?.taskList?.sort((a, b) => a.order - b.order);
				if (_taskList && _taskList.length) {
					_taskList.forEach((subTask) => {
						const obj = {
							name: subTask.type || '',
							status: subTask.status,
							bgTime: subTask.bgTime,
							edTime: subTask.edTime,
							order: subTask.order || 0,
							msg: subTask.msg || '',
							parentName: task.task,
							level: 2,
							isRefresh: task.task === 'llmTask'
						};

						taskProgressDetail.value.push(obj);
					});
				}
			});

			if (!flag.value) {
				taskProgressDialog.value.visible = true;
				flag.value = true;
			}
		})
		.catch((err) => {
			console.error(getErrorMessage(err));
		})
		.finally(() => {
			pollAILessonTaskProgress();
		});
};

// 设置流程线的长度
const taskLineLength = ref<number>(0);
const setTaskLineLength = () => {
	nextTick(() => {
		const taskNodeList = document.querySelectorAll('.circle-flag');
		console.log(111, taskNodeList);
		taskLineLength.value =
			taskNodeList[taskNodeList.length - 1].getBoundingClientRect().top -
			taskNodeList[0].getBoundingClientRect().top;
		const verticalLine = document.querySelector<HTMLDivElement>('.vertical-line');
		if (verticalLine) {
			verticalLine.style.height = `${taskLineLength.value}px`;
			verticalLine.style.transform = `translateY(4px)`;
		}
	});
};

// resize事件
const resizeEvent = () => {
	if (taskProgressDialog.value.visible) {
		setTimeout(() => {
			setTaskLineLength();
		}, 300);
	}
};

// 分析名称映射
const aiTaskNameMap = ref<{ [key: string]: string }>({
	pptTask: 'ppt',
	llmTask: 'llm',
	audioTask: 'audio',
	behaviorRecognitionResp: 'action',
	resultProcess: 'result'
});
// 刷新分析详情
const onRefreshHandle = (row: TaskProgressDetailItem) => {
	if (row.level === 1) {
		const _name = aiTaskNameMap.value[row.name || ''];
		openAILessonTask(curLesson.value, _name);
	} else if (row.level === 2) {
		const _name = aiTaskNameMap.value[row.parentName || ''];
		openAILessonTask(curLesson.value, _name, [row.name]);
	}
};

/** 观看点播相关 */
const curPlayerLesson = ref<TableDataItem | null>(null);
const fragmentList = ref<FragmentItem[]>([]);
const activeFragmentKey = ref<string[]>([]);
const videojsData = ref<VideoDataType | null>(null);
const isCovered = ref(false);
const isDelete = ref(false);
let playDialogVisible = ref<boolean>(false);
const getPlyerList = async (lesson: TableDataItem) => {
	curPlayerLesson.value = lesson;
	let data = null;

	const is404 = instance?.proxy?.$globalData?.is404;
	try {
		data = await getResourceByLessonCodeAPI(
			lesson.lessonCode || '',
			typeof is404 === 'boolean' ? is404 : true
		);
	} catch (error) {
		console.error(getErrorMessage(error));
	}
	const list = data?.length
		? data?.map((item) => ({
				...item,
				id: item.id || uuidv4()
		  }))
		: [];
	const listResult = list.filter((item2) => {
		return item2.files.length !== 0;
	});
	// deviceTypeId===1录播主机，deviceTypeId===2摄像头
	// purpose 1:老师；2:学生
	listResult.sort((a, b) => {
		return a?.device?.deviceTypeId - b?.device?.deviceTypeId;
	});
	listResult.sort((a, b) => {
		return a?.device?.purpose - b?.device?.purpose;
	});
	fragmentList.value = listResult;
	activeFragmentKey.value = listResult.map((item) => item.id);
	if (
		fragmentList.value[0] &&
		fragmentList.value[0].files[0] &&
		fragmentList.value[0].files[0].url
	) {
		videojsData.value = {
			source: fragmentList.value[0].files[0].url,
			videoId: fragmentList.value[0].files[0].id,
			name: fragmentList.value[0].files[0].filename
		};
		isCovered.value = fragmentList.value[0].status === 6;
		isDelete.value = fragmentList.value[0].status === 7;
		playDialogVisible.value = true;
	} else {
		ElMessage.warning('暂无录像资源!');
	}
};
// 格式化名称
const fitlerFileName = (name: string) => {
	const site = name.lastIndexOf('/');
	// 截取最后一个/后的值
	return name.slice(site + 1);
};
// 改变播放片段
const changePlayFragment = (file: FileType, status: number) => {
	videojsData.value = {
		source: file.url,
		videoId: file.id,
		name: file.filename
	};
	isCovered.value = status === 6;
	isDelete.value = status === 7;
};
// 下载播放片段
const downloadFragment = async (file: FileType, item: FragmentItem) => {
	const attname = await getLessonDetail(item);
	let renameUrl = '';
	if (file.url.includes('?')) {
		renameUrl = `${file.url}&attname=${attname}`;
	} else {
		renameUrl = `${file.url}?attname=${attname}`;
	}
	window.open(renameUrl);
};
// 获取课堂详情
const getLessonDetail = async (item: FragmentItem) => {
	// 从课堂名中截取课程名
	const attname = `${
		curPlayerLesson.value?.name
			? `${curPlayerLesson.value.name.replace(/\s*\d{4}-\d{2}-\d{2}$/, '')?.trim()}-`
			: ''
	}${curPlayerLesson.value?.teacherNames ? `${curPlayerLesson.value.teacherNames}-` : ''}${
		curPlayerLesson.value?.beginTime
			? `${formatTime(curPlayerLesson.value.beginTime, 'YYYY_MM_DDTHH_mm_ss')}-`
			: ''
	}${curPlayerLesson.value?.roomName ? `${curPlayerLesson.value.roomName}-` : ''}${
		item.device?.name || '未知视角'
	}.mp4`;
	return Promise.resolve(attname);
};
// 复制链接
const copyUrl = async (url: string, item: FragmentItem) => {
	const cInput = document.createElement('input');
	const attname = await getLessonDetail(item);

	let renameUrl = '';
	if (url.includes('?')) {
		renameUrl = `${url}&attname=${attname}`;
	} else {
		renameUrl = `${url}?attname=${attname}`;
	}
	cInput.value = renameUrl;
	document.body.appendChild(cInput);
	cInput.select();
	document.execCommand('Copy');
	ElMessage.success('复制成功');
	cInput.remove();
};
</script>
<style scoped lang="scss">
.analysis-task-manage-page {
	display: flex;
	flex-direction: column;
	height: 100%;
}

:deep(.self-dialog:not(.video-play-dialog)) {
	.el-dialog__body {
		height: 60rem;
		overflow: overlay;
	}
}

:deep(.progress-dialog) {
	.el-dialog__body {
		height: calc(100vh - 6rem - 8rem) !important;
	}
}

:deep(.video-play-dialog) {
	width: 120rem;
}

.config-dialog-wrap {
	.build-list-wrap {
		margin-bottom: 3rem;
		flex-wrap: wrap;
		border-bottom: 1px solid $border-color-primary;
		position: relative;
		padding: 1rem;
		padding-top: 2rem;

		.floor-name {
			position: absolute;
			top: -0.6rem;
			font-family: $font-family-bold;
			font-size: $font-size-large-1;
			color: $text-color-regular;
		}

		.floor-item {
			margin: 1rem 0;

			.floor-text {
				margin-bottom: 0.4rem;
				margin-left: 1rem;
				font-size: $font-size-base;
			}
		}

		.room-list-wrap {
			display: flex;
			flex-wrap: wrap;
			padding-left: 0.4rem;

			.room-item {
				margin: 0.6rem;
				padding: 1rem;
				font-size: $font-size-base;
				background: rgba(230, 232, 237, 0.7);
				color: $text-color-secondary;
				cursor: pointer;
				border-radius: 0.4rem;
				width: 12rem;
				text-align: center;
				text-wrap: nowrap;
				overflow: hidden;
				text-overflow: ellipsis;
			}

			.room-item-active {
				background: color.adjust($color-brand, $lightness: 12%);
				color: $text-color-white;
			}
		}
	}
}

.progress-dialog-wrap {
	height: 100%;

	:deep(.el-table .cell) {
		position: relative;
		overflow: visible;
		text-align: inherit;
	}

	:deep(.el-table) {
		height: 100%;

		td:first-child {
			.cell {
				display: flex;
				align-items: center;
			}
		}
	}

	.task-circle {
		display: inline-block;
		width: 7px;
		height: 7px;
		border-radius: 3.5px;
		background-color: $color-brand;
		margin-right: 1rem;
		margin-left: 5rem;
		position: relative;
	}

	.subtask-circle {
		display: inline-block;
		width: 5px;
		height: 5px;
		border-radius: 2.5px;
		background-color: $color-brand;
		margin-right: 1.6rem;
		margin-left: 7rem;
		position: relative;
	}

	.subtask-circle::before {
		content: '';
		display: inline-block;
		position: absolute;
		right: 0;
		top: 2px;
		width: 2rem;
		border-bottom: 1px dashed $color-brand;
	}

	.vertical-line {
		position: absolute;
		top: 0;
		left: 3px;
		border-left: 1px dashed $color-brand;
		z-index: 1000;
	}

	.el-icon-refresh {
		cursor: pointer;
		color: $color-brand;
		margin-left: 0.5rem;
	}

	.refresh {
		font-size: $font-size-base;
		font-weight: 400;
		color: $color-brand;
		cursor: pointer;
	}

	.has-font-size {
		font-size: $font-size-base;
	}
}

.video-play-content {
	height: 45rem;
	display: flex;
	justify-content: space-between;
	align-items: center;

	.player-wrap {
		width: 80rem;
		height: 100%;
		margin-right: 2rem;
	}

	.fragment-box {
		flex: 1;
		border: 1px solid $border-color-primary;
		border-radius: 0.4rem;
		height: 100%;
		overflow: auto;

		:deep(.el-collapse) {
			border: none;

			.el-collapse-item__wrap {
				border-color: $border-color-primary;
			}

			.el-collapse-item__header {
				padding-left: 1rem;
				padding-right: 1rem;
				min-height: 4rem;
				line-height: 4rem;
				color: $text-color-regular;
				font-size: $font-size-base;
			}

			.el-collapse-item__content {
				padding-bottom: 0;
				color: $text-color-regular;
				font-size: $font-size-small-1;
			}
		}

		.fragment {
			padding: 0.6rem 2rem;
			font-size: $font-size-small-1;
			display: flex;
			justify-content: space-between;
			align-items: center;

			.file-name {
				width: 69%;
				cursor: pointer;
				overflow: hidden;
				text-overflow: ellipsis;
				white-space: nowrap;
			}

			.copy-btn,
			.download-btn {
				cursor: pointer;
			}

			.copy-btn:hover,
			.download-btn:hover {
				color: $color-brand;
			}
		}

		.fragment.active {
			.file-name {
				color: $color-brand;
			}
		}
	}
}
</style>
